﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Pampa.CRUD.Configuration;
using Pampa.CRUD.Core;
using Pampa.Grid.Core;
using Pampa.Grid.Core.Actions;
using Pampa.Grid.Core.Filters;
using Pampa.Grid.Data;
using Pampa.Grid.UI.CustomControls;
using Pampa.MVC.Fluent.Common;
using Pampa.MVC.Fluent.Crud.Items;

namespace Pampa.MVC.Fluent.Grid
{
    public abstract class CustomGridConfig<T> : AbstractBuilder
    {
        private readonly CustomGrid _grid;

        public CustomGridConfig()
        {
            _grid = new CustomGrid();
        }

        /// <summary>
        /// Start configuration
        /// </summary>
        public abstract void Init();

        #region Columns

        protected ColumnBuilder<T> AddStringColumn(Expression<Func<T, object>> property, string title = null)
        {
            var field = GetId(property);
            var column = _grid.AddColumn(field, title ?? field, ColumnType.String);
            return new ColumnBuilder<T>(this, _grid, column);
        }

        protected ColumnBuilder<T> AddNumberColumn(Expression<Func<T, object>> property, string title = null)
        {
            var field = GetId(property);
            var column = _grid.AddColumn(field, title ?? field, ColumnType.Number);
            return new ColumnBuilder<T>(this, _grid, column);
        }

        protected ColumnBuilder<T> AddDateColumn(Expression<Func<T, object>> property, string title = null)
        {
            var field = GetId(property);
            var column = _grid.AddColumn(field, title ?? field, ColumnType.Date);
            return new ColumnBuilder<T>(this, _grid, column);
        }

        protected ColumnBuilder<T> AddBoolColumn(Expression<Func<T, object>> property, string title = null)
        {
            var field = GetId(property);
            var column = _grid.AddColumn(field, title ?? field, ColumnType.Bool);
            return new ColumnBuilder<T>(this, _grid, column);
        }

        #endregion

        #region Quick Filters Definition

        protected QuickFilterStringBuilder<T> AddQuickFilter(Expression<Func<T, string>> property)
        {
            var qfDefinition = new QuickFilterDefinition();
            qfDefinition.Field = GetId(property);
            qfDefinition.ValueType = typeof(string);

            _grid.QuickFilterDefinitions.Add(qfDefinition);

            return new QuickFilterStringBuilder<T>(qfDefinition, this.QuickFilterId);
        }

        protected QuickFilterNumberBuilder<T> AddQuickFilter(Expression<Func<T, int>> property)
        {
            return AddQuickNumberFilter<int>(property);
        }

        protected QuickFilterNumberBuilder<T> AddQuickFilter(Expression<Func<T, int?>> property)
        {
            return AddQuickNumberFilter<int?>(property);
        }

        protected QuickFilterNumberBuilder<T> AddQuickFilter(Expression<Func<T, Single>> property)
        {
            return AddQuickNumberFilter<Single>(property);
        }

        protected QuickFilterNumberBuilder<T> AddQuickFilter(Expression<Func<T, Single?>> property)
        {
            return AddQuickNumberFilter<Single?>(property);
        }

        protected QuickFilterNumberBuilder<T> AddQuickFilter(Expression<Func<T, Double>> property)
        {
            return AddQuickNumberFilter<Double>(property);
        }

        protected QuickFilterNumberBuilder<T> AddQuickFilter(Expression<Func<T, Double?>> property)
        {
            return AddQuickNumberFilter<Double?>(property);
        }

        protected QuickFilterNumberBuilder<T> AddQuickFilter(Expression<Func<T, Decimal>> property)
        {
            return AddQuickNumberFilter<Decimal>(property);
        }

        protected QuickFilterNumberBuilder<T> AddQuickFilter(Expression<Func<T, Decimal?>> property)
        {
            return AddQuickNumberFilter<Decimal?>(property);
        }

        protected QuickFilterNumberBuilder<T> AddQuickFilter(Expression<Func<T, DateTime>> property)
        {
            return AddQuickNumberFilter<DateTime>(property);
        }

        protected QuickFilterNumberBuilder<T> AddQuickFilter(Expression<Func<T, DateTime?>> property)
        {
            return AddQuickNumberFilter<DateTime?>(property);
        }

        protected QuickFilterUnknownTypeBuilder<T> AddQuickFilter<TEntity>(Expression<Func<T, TEntity>> property)
        {
            var qfDefinition = new QuickFilterDefinition();
            qfDefinition.Field = GetId(property);
            qfDefinition.ValueType = typeof(TEntity);

            _grid.QuickFilterDefinitions.Add(qfDefinition);

            return new QuickFilterUnknownTypeBuilder<T>(qfDefinition, this.QuickFilterId);
        }

        #endregion

        #region Actions

        protected ActionItemBuilder<T> AddItemAction()
        {
            var item = new ItemAction();
            _grid.ItemActions.Add(item);
            return new ActionItemBuilder<T>(item);
        }

        protected ActionItemBuilder<T> AddEditAction()
        {
            var item = new ItemAction();
            item.Image = "Pampa.Common/edit.gif";
            item.Parameters.Add("@Id");
            item.Text = "Edit " + typeof (T).Name;
            _grid.ItemActions.Add(item);
            return new ActionItemBuilder<T>(item);
        }

        protected ActionItemBuilder<T> AddDeleteAction()
        {
            var item = new ItemAction();
            item.Image = "Pampa.Common/delete.gif";
            item.Parameters.Add("@Id");
            item.Text = "Delete " + typeof(T).Name;
            _grid.ItemActions.Add(item);
            return new ActionItemBuilder<T>(item);
        }

        protected ActionMassiveBuilder<T> AddMassiveAction()
        {
            var item = new MassiveAction();
            _grid.MasiveActions.Add(item);
            return new ActionMassiveBuilder<T>(item);
        }

        #endregion

        #region Data Reader

        protected void DataReader(GridDataReader dataReader)
        {
            _grid.DataReader = dataReader;
        }

        #endregion

        #region Internal Properties

        internal CustomGrid Grid
        {
            get { return _grid; }
        }

        internal string QuickFilterId
        {
            get; set;
        }

        #endregion

        #region Private Functions

        private QuickFilterNumberBuilder<T> AddQuickNumberFilter<T2>(Expression<Func<T, T2>> property)
        {
            var qfDefinition = new QuickFilterDefinition();
            qfDefinition.Field = GetId(property);
            qfDefinition.ValueType = typeof(T2);

            _grid.QuickFilterDefinitions.Add(qfDefinition);

            return new QuickFilterNumberBuilder<T>(qfDefinition, this.QuickFilterId);
        }

        #endregion
    }
}
